﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using KingOfCSharp.iHunter;
using System.Net.Mail;
using System.Data;
using System.IO;
namespace KingOfCSharp.iHunter.Plugins.Email
{
    public class EmailChannel : IChannel
    {
        string Eguid;
        DataSet dataSet;
        string channelName;
        string protocal;
        string s_server, r_server;
        int s_port, r_port;
        string username, password;
        bool s_ssl, r_ssl, opt_d;
        LumiSoft.Net.POP3.Client.POP3_Client pop3_Client;
        LumiSoft.Net.IMAP.Client.IMAP_Client imap_Client;
        SmtpClient smtp_Client;
        public EmailChannel(string server,int port, string user,string pass,bool ssl,bool del)
        {
            dataSet = new DataSet();
            s_ssl = ssl;
            s_server = server;
            s_port = port;
            username = user;
            password = pass;
            opt_d = del;
            protocal = "1";
            imap_Client = new LumiSoft.Net.IMAP.Client.IMAP_Client();
            //pop3_Client = new LumiSoft.Net.POP3.Client.POP3_Client();
            if (opt_d == false)
            {
                channelName = r_server + username;
                if (!dataSet.Tables.Contains(channelName))
                {

                    DataTable dt = new DataTable(channelName);
                    DataColumn dc = new DataColumn("uid");
                    dt.Columns.Add(dc);
                    dt.PrimaryKey = new DataColumn[] { dc };
                    dataSet.Tables.Add(dt);
                }
            }
        }
        public EmailChannel(string setting,DataSet ds,string guid)
        {
            dataSet = ds;
            XmlDocument doc = new XmlDocument();
            doc.LoadXml(setting);
            XmlElement root = doc["EmailChannelSettings"];
            protocal = root["protocal"].InnerText;
            s_server = root["s_server"].InnerText;
            r_server = root["r_server"].InnerText;
            s_port = Convert.ToInt32(root["s_port"].InnerText);
            r_port = Convert.ToInt32(root["r_port"].InnerText);
            username = root["username"].InnerText;
            password = root["password"].InnerText;
            s_ssl = root["s_ssl"].InnerText == "true" ? true : false;
            r_ssl = root["r_ssl"].InnerText == "true" ? true : false;
            opt_d = root["opt_d"].InnerText == "true" ? true : false;
            Eguid = guid;
            if (protocal == "1")
            {
                imap_Client = new LumiSoft.Net.IMAP.Client.IMAP_Client();
            }
            else
            {
                pop3_Client = new LumiSoft.Net.POP3.Client.POP3_Client();

            }
            if (opt_d == false)
            {
                channelName = "EmailDataSet";
                if (!dataSet.Tables.Contains(channelName))
                {

                    DataTable dt = new DataTable(channelName);
                    DataColumn dc1 = new DataColumn("uid");                  
                    dt.Columns.Add(dc1);
                    DataColumn  dc2 = new DataColumn("guid");
                    dt.Columns.Add(dc2);
                    dt.PrimaryKey = new DataColumn[] { dc1,dc2};
                    dataSet.Tables.Add(dt);
                }
            }
        }

        #region IChannel Members

        public IEnumerable<IMessage> DownloadMessages(DateTime startTime, DateTime endTime, string attachmentDirectoryPath)
        {
                if (protocal == "0")
                {
                    LumiSoft.Net.POP3.Client.POP3_MessagesInfo infos;
                    Message message;
                    //List<IMessage> messages = new List<IMessage>();
                    try
                    {
                        
                        pop3_Client.Connect(r_server, r_port, r_ssl);
                        pop3_Client.Authenticate(username, password, false);

                         infos = pop3_Client.GetMessagesInfo();
                    }
                    catch (Exception e)
                    {
                        throw new System.Net.WebException(e.Message);
                    }
                    foreach (LumiSoft.Net.POP3.Client.POP3_MessageInfo info in infos)
                    {

                        if (!opt_d)
                        {
                            DataTable dt = dataSet.Tables[channelName];
                            if (info.MessageUID != null)
                            {
                                object[] keys = new object[] {info.MessageUID,Eguid };
                                if (dt.Rows.Contains(keys))
                                {
                                    continue;
                                }
                                else
                                {
                                    dt.Rows.Add(keys);
                                }
                            }
                        }
                        byte[] bytes = pop3_Client.GetMessage(info);
                        LumiSoft.Net.Mime.Mime mime = LumiSoft.Net.Mime.Mime.Parse(bytes);
                        if (mime.MainEntity.Date != null)
                        {
                            if (mime.MainEntity.Date < startTime || mime.MainEntity.Date > endTime)
                            {
                                if (opt_d == true)
                                {
                                    pop3_Client.DeleteMessage(info.MessageNumber);
                                }
                                continue;
                            }
                        }
                        else
                        {
                            continue;
                        }
                        message = new Message(Guid.Empty, info.MessageUID.GetHashCode());
                        message.EditorGuid = KingOfCSharp.iHunter.UI.HtmlEditorProvider.Guid;
                        string author = mime.MainEntity.From.ToAddressListString();
                        if (author == null)
                        {
                            author = string.Empty;
                        }
                        else
                        {
                            author = author.Substring(author.IndexOf("<"),author.IndexOf(">")-author.IndexOf("<")+1);
                        }
                        message.Author = author;
                        message.Title = mime.MainEntity.Subject == null ? string.Empty : mime.MainEntity.Subject;
                        if (mime.MainEntity.Date == null || mime.MainEntity.Date == DateTime.MinValue)
                        {
                            message.PublishTime = new DateTime(1900, 1, 1);
                            message.UpdateTime = new DateTime(1900, 1, 1);
                        }
                        else
                        {
                            message.PublishTime = mime.MainEntity.Date;
                            message.UpdateTime = mime.MainEntity.Date;
                        }
                        message.Receiver = mime.MainEntity.To.ToAddressListString() == null ? string.Empty : mime.MainEntity.To.ToAddressListString();
                        message.Content = mime.BodyHtml == null ? string.Empty : mime.BodyHtml;
                        message.CustomFields["PlainText"] = mime.BodyText == null ? string.Empty : mime.BodyText;
                        //message.CustomFields["mnumber"] = info.MessageNumber.ToString();
                        //message.CustomFields["muid"] = info.MessageUID;
                        //message.CustomFields["size"] = info.MessageSize.ToString();
                        if (mime.Attachments.Length > 0)
                        {
                            LumiSoft.Net.Mime.MimeEntity mat;
                            Attachment at;
                            for (int i = 0; i < mime.Attachments.Length; i++)
                            {
                                mat = mime.Attachments[i];
                                string path = attachmentDirectoryPath + "\\" + mat.ContentDisposition_FileName;
                                while (File.Exists(path))
                                {
                                    path += "0";
                                }
                                mat.DataToFile(path);
                                string fileType = mat.ContentDisposition_FileName.Substring(mat.ContentDisposition_FileName.LastIndexOf("."));
                                if (fileType == null)
                                {
                                    fileType = string.Empty;
                                }
                                at = new Attachment(Guid.Empty, mat.ContentDisposition_FileName, fileType,
                                        mat.Data.LongLength, string.Empty, path, mat.ContentDescription);
                                message.Attachments.Add(at);
                            }
                        }
                        if (opt_d == true)
                        {
                            pop3_Client.DeleteMessage(info.MessageNumber);
                        }
                        else
                        {

                        }
                        //messages.Add(message);
                        yield return message;
                    }
                    pop3_Client.Disconnect();
                    yield break;
                }
                else
                {
                    Message message;
                    imap_Client.Connect(r_server, r_port, r_ssl);
                    string imap_user;
                    if (r_server.Contains("imap"))
                    {
                        imap_user = username + "@" + r_server.Substring(r_server.IndexOf(".") + 1);

                        imap_Client.Authenticate(imap_user, password);
                        imap_Client.SelectFolder("Inbox");
                        LumiSoft.Net.IMAP.IMAP_SequenceSet sequence_set = new LumiSoft.Net.IMAP.IMAP_SequenceSet();

                        sequence_set.Parse("1:*");
                        LumiSoft.Net.IMAP.Client.IMAP_FetchItem[] msgsInfos = imap_Client.FetchMessages(sequence_set, LumiSoft.Net.IMAP.Client.IMAP_FetchItem_Flags.UID | LumiSoft.Net.IMAP.Client.IMAP_FetchItem_Flags.MessageFlags, false, true);

                        bool flag = false;
                        StringBuilder to_Paser = new StringBuilder();
                        foreach (LumiSoft.Net.IMAP.Client.IMAP_FetchItem info in msgsInfos)
                        {
                            if (!opt_d)
                            {
                                object[] keys = new object[] {info.UID,Eguid };
                                DataTable dt = dataSet.Tables[channelName];
                                if (dt.Rows.Contains(keys))
                                {
                                    continue;
                                }
                                else
                                {
                                    if (!flag)
                                    {
                                        flag = true;
                                        to_Paser.Append(info.MessageNumber);

                                    }
                                    else
                                    {
                                        to_Paser.Append("," + info.MessageNumber);
                                    }
                                    dt.Rows.Add(keys);

                                }
                            }

                        }
                        if (to_Paser.ToString() == string.Empty)
                        {
                            yield break;
                        }
                        sequence_set.Parse(to_Paser.ToString());
                        if (opt_d == true)
                        {
                            msgsInfos = imap_Client.FetchMessages(sequence_set, LumiSoft.Net.IMAP.Client.IMAP_FetchItem_Flags.Message | LumiSoft.Net.IMAP.Client.IMAP_FetchItem_Flags.UID, true, true);

                        }
                        else
                        {
                            msgsInfos = imap_Client.FetchMessages(sequence_set, LumiSoft.Net.IMAP.Client.IMAP_FetchItem_Flags.Message | LumiSoft.Net.IMAP.Client.IMAP_FetchItem_Flags.UID, false, true);

                        }

                        foreach (LumiSoft.Net.IMAP.Client.IMAP_FetchItem info in msgsInfos)
                        {
                            LumiSoft.Net.Mime.Mime mime = LumiSoft.Net.Mime.Mime.Parse(info.Data);
                            if (mime.MainEntity.Date != null)
                            {
                                if (mime.MainEntity.Date < startTime || mime.MainEntity.Date > endTime)
                                {
                                    if (opt_d == true)
                                    {
                                        pop3_Client.DeleteMessage(info.MessageNumber);
                                    }
                                    continue;
                                }
                            }
                            else
                            {
                                continue;
                            }
                            message = new Message(Guid.Empty, info.UID);
                            message.EditorGuid = KingOfCSharp.iHunter.UI.HtmlEditorProvider.Guid;
                            string author = mime.MainEntity.From.ToAddressListString();
                            if (author == null)
                            {
                                author = string.Empty;
                            }
                            else
                            {
                                author = author.Substring(author.IndexOf("<"), author.IndexOf(">") - author.IndexOf("<") + 1);
                            }
                            message.Author = author;
                            message.Title = mime.MainEntity.Subject == null ? string.Empty : mime.MainEntity.Subject;
                            if (mime.MainEntity.Date == null || mime.MainEntity.Date == DateTime.MinValue)
                            {
                                message.PublishTime = new DateTime(1900, 1, 1);
                                message.UpdateTime = new DateTime(1900, 1, 1);
                            }
                            else
                            {
                                message.PublishTime = mime.MainEntity.Date;
                                message.UpdateTime = mime.MainEntity.Date;
                            }
                            message.Receiver = mime.MainEntity.To.ToAddressListString() == null ? string.Empty : mime.MainEntity.To.ToAddressListString();
                            message.Content = mime.BodyHtml == null ? string.Empty : mime.BodyHtml;
                            message.CustomFields["PlainText"] = mime.BodyText == null ? string.Empty : mime.BodyText;
                            //message.CustomFields["mnumber"] = info.MessageNumber.ToString();
                            //message.CustomFields["muid"] = info.MessageUID;
                            //message.CustomFields["size"] = info.Size.ToString();
                            if (mime.Attachments.Length > 0)
                            {
                                LumiSoft.Net.Mime.MimeEntity mat;
                                Attachment at;
                                for (int i = 0; i < mime.Attachments.Length; i++)
                                {
                                    mat = mime.Attachments[i];
                                    string path = attachmentDirectoryPath + "\\" + mat.ContentDisposition_FileName;
                                    while (File.Exists(path))
                                    {
                                        path += "0";
                                    }
                                    mat.DataToFile(path);
                                    string fileType = mat.ContentDisposition_FileName.Substring(mat.ContentDisposition_FileName.LastIndexOf("."));
                                    if (fileType == null)
                                    {
                                        fileType = string.Empty;
                                    }
                                    string ds = mat.ContentDescription == null ? string.Empty : mat.ContentDescription;
                                    at = new Attachment(Guid.Empty, mat.ContentDisposition_FileName, fileType,
                                            mat.Data.LongLength, string.Empty, path, ds);
                                    message.Attachments.Add(at);
                                }
                            }

                            yield return message;

                        }
                    }
                    else
                    {
                        imap_user = username + "@" + r_server;
                        imap_Client.Authenticate(imap_user, password);
                        imap_Client.SelectFolder("Inbox");
                        LumiSoft.Net.IMAP.IMAP_SequenceSet sequence_set = new LumiSoft.Net.IMAP.IMAP_SequenceSet();
                        LumiSoft.Net.IMAP.Client.IMAP_FetchItem[] msgsInfos;
                        sequence_set.Parse("1:*");
                        msgsInfos = imap_Client.FetchMessages(sequence_set, LumiSoft.Net.IMAP.Client.IMAP_FetchItem_Flags.UID | LumiSoft.Net.IMAP.Client.IMAP_FetchItem_Flags.MessageFlags | LumiSoft.Net.IMAP.Client.IMAP_FetchItem_Flags.Message, opt_d, true);
                        foreach (LumiSoft.Net.IMAP.Client.IMAP_FetchItem info in msgsInfos)
                        {
                            if (!opt_d)
                            {
                                DataTable dt = dataSet.Tables[channelName];
                                if (info.UID != 0)
                                {
                                    object[] keys = new object[] { info.UID,Eguid};
                                    if (dt.Rows.Contains(keys))
                                    {
                                        continue;
                                    }
                                    else
                                    {
                                        dt.Rows.Add(keys);
                                    }
                                }
                            }
                            LumiSoft.Net.Mime.Mime mime = LumiSoft.Net.Mime.Mime.Parse(info.Data);
                            if (mime.MainEntity.Date != null)
                            {
                                if (mime.MainEntity.Date < startTime || mime.MainEntity.Date > endTime)
                                {
                                    if (opt_d == true)
                                    {
                                        pop3_Client.DeleteMessage(info.MessageNumber);
                                    }
                                    continue;
                                }
                            }
                            else
                            {
                                continue;
                            }
                            message = new Message(Guid.Empty, info.UID);
                            message.EditorGuid = KingOfCSharp.iHunter.UI.HtmlEditorProvider.Guid;
                            string author = mime.MainEntity.From.ToAddressListString();
                            if (author == null)
                            {
                                author = string.Empty;
                            }
                            else
                            {
                                author = author.Substring(author.IndexOf("<"), author.IndexOf(">") - author.IndexOf("<") + 1);
                            }
                            message.Author = author;
                            message.Title = mime.MainEntity.Subject == null ? string.Empty : mime.MainEntity.Subject;
                            if (mime.MainEntity.Date == null || mime.MainEntity.Date == DateTime.MinValue)
                            {
                                message.PublishTime = new DateTime(1900, 1, 1);
                                message.UpdateTime = new DateTime(1900, 1, 1);
                            }
                            else
                            {
                                message.PublishTime = mime.MainEntity.Date;
                                message.UpdateTime = mime.MainEntity.Date;
                            }
                            message.Receiver = mime.MainEntity.To.ToAddressListString() == null ? string.Empty : mime.MainEntity.To.ToAddressListString();
                            message.Content = mime.BodyHtml == null ? string.Empty : mime.BodyHtml;
                            message.CustomFields["PlainText"] = mime.BodyText == null ? string.Empty : mime.BodyText;
                            //message.CustomFields["mnumber"] = info.MessageNumber.ToString();
                            //message.CustomFields["muid"] = info.MessageUID;
                            //message.CustomFields["size"] = info.Size.ToString();
                            if (mime.Attachments.Length > 0)
                            {
                                LumiSoft.Net.Mime.MimeEntity mat;
                                Attachment at;
                                for (int i = 0; i < mime.Attachments.Length; i++)
                                {
                                    mat = mime.Attachments[i];
                                    string path = attachmentDirectoryPath + "\\" + mat.ContentDisposition_FileName;
                                    while (File.Exists(path))
                                    {
                                        path += "0";
                                    }
                                    mat.DataToFile(path);
                                    string fileType = mat.ContentDisposition_FileName.Substring(mat.ContentDisposition_FileName.LastIndexOf("."));
                                    if (fileType == null)
                                    {
                                        fileType = string.Empty;
                                    }
                                    string ds = mat.ContentDescription == null ? string.Empty : mat.ContentDescription;
                                    at = new Attachment(Guid.Empty, mat.ContentDisposition_FileName, fileType,
                                            mat.Data.LongLength, string.Empty, path, ds);
                                    message.Attachments.Add(at);
                                }
                            }

                            yield return message;
                        }
                    }
                    imap_Client.Disconnect();
                    yield break;
                }
        }

      
        public bool SendMessage(IMessage message)
        {
            smtp_Client = new SmtpClient(s_server,s_port);
            if(s_ssl)
            {
                smtp_Client.EnableSsl = true;
            }
            smtp_Client.UseDefaultCredentials = false;
            string smtp_User;
            if (s_server.Contains("smtp"))
            {
                smtp_User = username + "@" + s_server.Substring(s_server.IndexOf(".") + 1);
            }
            else
            {
                smtp_User = username + "@" + s_server;
            }
            smtp_Client.Credentials = new System.Net.NetworkCredential(smtp_User,password);
            smtp_Client.DeliveryMethod = SmtpDeliveryMethod.Network;

            MailMessage mm = new MailMessage(smtp_User, message.Receiver, message.Title, message.Content);
            if(message.Attachments.Count > 0)
            {
                System.Net.Mail.Attachment matt;
                foreach (IAttachment att in message.Attachments)
                {

                    matt = new System.Net.Mail.Attachment(att.LocalPath);
                    mm.Attachments.Add(matt);
                }
            }
            mm.BodyEncoding = System.Text.Encoding.UTF8;
            mm.IsBodyHtml = true;

            smtp_Client.Send(mm);
           
            return true;
        }

        public bool ReplyMessage(IMessage original, IMessage reply)
        {
            Message message = new Message();
            message.Receiver = original.Author.Substring(original.Author.IndexOf("<") + 1, original.Author.IndexOf(">") - original.Author.IndexOf("<")-1);
            message.Title = "Re: " + original.Title;
            StringBuilder sb = new StringBuilder();
            sb.Append(reply.Content + "<br><br>");
            sb.Append(original.PublishTime.ToString() +"  "+ original.Author + "<br>");
            sb.Append(original.CustomFields["PlainText"]);
            message.Content = sb.ToString();
            if (reply.Attachments.Count > 0)
            {
                foreach (IAttachment att in reply.Attachments)
                {
                    message.Attachments.Add(att);
                }
            }
            SendMessage(message);

            return true;


        }

        public void CancelBlockingCall()
        {
            //do nothing
        }

        public event PluginErrorEventHandler ErrorOccur;

        #endregion

        #region IChannel Members

        public bool DownloadAttachment(IAttachment attachment)
        {
            return true;
        }

        #endregion

        #region IDisposable 成员

        public void Dispose()
        {
            //do nothing
        }

        #endregion

        #region IChannel Members


        public IEnumerable<IMessage> UpdateMessage(IMessage message)
        {
            yield break;
        }

        #endregion
    }
}
